# Зашифровали демоны!

Караул! Помогите! Всё, всё, что нажито непосильным трудом, всё пошифровалось! 
Три базы данных, три жестких диска заграничных, три антивируса отечественных, сервер выделенный… три… сервера. 
И чёрт бы с серверами, админы восстановят из бэкапов, но ведь эти ироды не пожалели даже фотографии моего любимого автомобиля, понимаешь? 
Вот за это точно их никогда не прощу! Посмотри, можно ли что-то с этим сделать.

# WriteUp

Ключом к решению является понимание того, что файл зашифрован с путем обычного **XOR'a** его содержимого с некоторым **8-байтным ключом**.

После осознания этого факта задача переходит во вполне практическую плоскость - восстановить этот самый ключ.

Так как первые **16 байтов** файла не зашифрованы, они нам дают немало информации.

**Во-первых**, по сигнатура в первых **8 байтах** мы понимаем, что исходный файл имел формат **PNG**.

Этот формат открыт, спецификации не трудно найти в Сети. 

Немного вчитавшись, мы понимаем, что **PNG** состоит из последовательности чанков, каждый из которых имеет вид:<br>
  **<4-байтовая длина данных><4 байта с заголовком, определяющим тип чанка><основное тело с данными чанка, длина которого совпадает с ранее указанным значением><4 байта c контрольной суммой данных чанка>**
  
Согласно стандарту, первым чанком в **PNG** должен идти **IHDR**, содержащий размеры файла.

И действительно, из незашифрованных **16 байт** мы узнаем, что дальше должен идти этот чанк с длиной тела данных **0xD**. 

Формат чанка, согласно спецификациям, имеет следующую структуру:
```
  struct IHDR {
    DWORD Hidth;
    DWORD Height;
    BYTE BitDepth;
    BYTE ColourType;
    BYTE CompressionMethod;
    BYTE FilterMethod;
    BYTE InterlaceMethod;
  };
```

Обращаем внимание, что на **ширину** и **высоту** отводится аж по **4 байта**! 
Но так как файл небольшой, можно предположить, что и ширина, и высота картинки вполне вмещаются в **2 младших байта**, а **2 старших байта занулены**. 

Это означает, что при **XOR'e** с ключом в них окажутся байты ключа. Значит, ключ имеет следующий вид:<br>
  **33 D1 ?? ?? 7D 56 ?? ??**<br>
Отлично, половина ключа уже восстановлена. Продолжим думать, как нам получить вторую его половину. 

Для этого посмотрим в конец файла. **Последние 12 байтов**, расположенные по оффсету **0x1E4A9E**, в зашифрованном виде выглядят как:<br>
  **9D 16 33 D1 47 68 33 12 33 54 53 53**<br>
Давайте дешифруем их с использованием имеющейся у нас части ключа:<br>
  **?? ?? 00 00 ?? ?? 4E 44 ?? ?? 60 82**<br>
А теперь снова смотрим в спецификацию. Согласно ей, данные **PNG**-файла должны заканчиваться чанком **IEND**. 

Особенность этого чанка заключается в том, что он имеет нулевую длину, и, следовательно, он полностью одинаково выглядит во всех **PNG**-файлах. 

Давайте возьмем любой другой **PNG**-файл и посмотрим, как данный чанк выглядит в нём:**
  **00 00 00 00 49 45 4E 44 AE 42 60 82**<br><br>
**Ничего не напоминает?** Дешифрованные байты в точности совпадают с байтами в чанке **IEND**! 
Значит, именно так и заканчивался исходный незашифрованный **PNG**-файл, что даёт нам возможность восстановить ключ полностью:<br>
  **33 D1 0E 2D 7D 56 9D 16**<br><br>
Теперь мы можем полностью расшифровать файл и прочесть флаг.


# Flag
RDG{Cryptography!sV3ry3asy}